<script setup lang="ts">
import type { PropType } from 'vue';

import { nextTick, ref, watch, provide, computed } from 'vue';

import html2pdf from 'html2pdf.js';

import { getDetailApi } from '#/api/manage/paper';

import ExamDetail from './exam-detail.vue';
import { questionTypeOptions } from "../const"
import { ElMessage } from 'element-plus';
import { $t } from '@vben/locales';

const titleName = import.meta.env.VITE_APP_TITLE
defineOptions({ name: 'Dialog' });

const props = defineProps({
  modelValue: {
    type: Object as PropType<ModelValueType>,
    required: true,
  },
});
defineEmits(['update:modelValue']);
interface ModelValueType {
  dialogVisible: boolean;
  paperId: string,
  papersName: string
}
const examDetail = ref<any>();
const examDialogRef = ref<HTMLElement>();
const paperType = ref<string>('a4')
const questionList = ref([])

provide('imageLoadedToUpdateDom', {
  resetPapNumber: async () => {
    if (examDialogRef?.value) {
      await nextTick(); // 等待DOM更新
      console.log('图片已加载')
      pageNumber.value = Math.ceil(examDialogRef?.value.offsetHeight / 1040);
    }
  }
});

const loading = ref(false);
const loadingBtn = ref(false);
const pageNumber = ref(0);

const handleClose = () => {
  props.modelValue.dialogVisible = false;
  examDetail.value = [];
};

const getDetail = (id: any) => {
  loading.value = true;
  getDetailApi({
    paperId: id,
  })
    .then((res) => {
      loading.value = false;
      questionList.value = res
      const group = groupByProperty(res, 'type')
      // 按照questionTypeOptions的value顺序排序
      const typeOrder = questionTypeOptions.map(q => q.value)
      examDetail.value = typeOrder
        .map(type => (group as any[]).find((g: any) => g[0]?.type === type))
        .filter(Boolean)
      console.log(examDetail.value)
    })
    .finally(() => {
      loading.value = false;
    });
};
const groupByProperty = (data: any, prop: any) => {
  if (!data) return [];
  return Object.values(
    data.reduce((acc: any, obj: any) => {
      const key = obj[prop];
      if (!acc[key]) {
        acc[key] = [];
      }
      acc[key].push(obj);
      return acc;
    }, {}),
  );
};
watch(props.modelValue, () => {
  if (props.modelValue.dialogVisible) {
    getDetail(props.modelValue.paperId);
  }
});

const examBodyStyle = computed(() => {
  if (paperType.value === 'a3') {
    return {
      width: '297mm',
      minHeight: '420mm',
      maxWidth: '297mm',
      maxHeight: 'none',
      overflow: 'visible'
    }
  }
  // 默认a4
  return {
    width: '210mm',
    minHeight: '297mm',
    maxWidth: '210mm',
    maxHeight: 'none',
    overflow: 'visible'
  }
})

async function printExam() {
  try {
    // 获取要导出的元素
    let element = document.querySelector('#examBody') as HTMLElement;

    if (!element) return

    // 预处理：确保所有图片都已加载完成
    const images = element.querySelectorAll('img');
    if (images.length > 0) {
      await Promise.all(
        Array.from(images).map(
          (img) =>
            new Promise((resolve) => {
              if (img.complete) {
                resolve(true);
              } else {
                img.onload = () => resolve(true);
                img.onerror = () => resolve(true);
              }
            })
        )
      );
    }

    // 等待DOM完全渲染
    await nextTick();

    // 预处理DOM：修复文字间距问题
    const textElements = element.querySelectorAll('p, div, span, td, th');
    textElements.forEach((el) => {
      const text = el.textContent || '';
      const htmlEl = el as HTMLElement;
      // 为包含括号的文本添加适当间距
      if (text.includes('(') || text.includes(')') || text.includes('（') || text.includes('）')) {
        htmlEl.style.wordSpacing = '0.1em'; // 减少间距
        htmlEl.style.letterSpacing = '0.05em'; // 减少间距
        // 为括号前后添加空格，确保不重叠
        htmlEl.innerHTML = htmlEl.innerHTML
          .replace(/\(/g, ' (')
          .replace(/\)/g, ') ')
          .replace(/（/g, ' （')
          .replace(/）/g, '） ')
          .replace(/\s+/g, ' '); // 清理多余空格
      }
      // 确保所有文本元素都有合适的行高
      htmlEl.style.lineHeight = '1.6';
    });

    // 配置选项
    const opt = {
      margin: [10, 10, 10, 10], // 减少边距，避免内容被压缩
      filename: `${props.modelValue.papersName}${new Date().toISOString().slice(0, 10)}.pdf`,
      enableLinks: false,
      image: { type: 'jpeg', quality: 0.95 },
      html2canvas: {
        scale: 1.5, // 降低scale，减少间距放大问题
        logging: false,
        useCORS: true,
        allowTaint: true,
        backgroundColor: '#ffffff',
        width: paperType.value === 'a3' ? 1123 : 794,
        height: undefined,
        scrollX: 0,
        scrollY: 0,
        windowWidth: paperType.value === 'a3' ? 1123 : 794,
        windowHeight: undefined,
        foreignObjectRendering: false,
        removeContainer: true,
        letterRendering: true, // 启用字母渲染，改善文字间距
        imageTimeout: 15000,
        ignoreElements: (element: Element) => {
          return element.classList.contains('ignore-pdf');
        },
        onclone: (clonedDoc: Document) => {
          // 在克隆的文档中应用样式
          const clonedElement = clonedDoc.querySelector('#examBody') as HTMLElement;
          if (clonedElement) {
            clonedElement.style.fontFamily = 'SimSun, Microsoft YaHei, sans-serif';
            clonedElement.style.wordSpacing = 'normal';
            clonedElement.style.letterSpacing = 'normal';
            clonedElement.style.lineHeight = '1.6';
            clonedElement.style.fontSize = '14px';
            clonedElement.style.padding = '15px'; // 减少内边距
            clonedElement.style.margin = '0';
          }
          
          // 特别处理包含括号的文本
          const textElements = clonedDoc.querySelectorAll('p, div, span, td, th');
          textElements.forEach((el) => {
            const htmlEl = el as HTMLElement;
            const text = htmlEl.textContent || '';
            if (text.includes('(') || text.includes(')') || text.includes('（') || text.includes('）')) {
              htmlEl.style.wordSpacing = '0.1em';
              htmlEl.style.letterSpacing = '0.05em';
            }
          });
          
          // 确保所有内联样式正确应用
          const styledElements = clonedDoc.querySelectorAll('[style]');
          styledElements.forEach((el) => {
            const htmlEl = el as HTMLElement;
            // 强制应用样式
            htmlEl.setAttribute('style', htmlEl.getAttribute('style') || '');
          });
        }
      },
      jsPDF: {
        unit: 'mm',
        format: paperType.value,
        orientation: 'portrait',
        compress: true,
        precision: 16,
        putOnlyUsedFonts: true,
        floatPrecision: 16,
      },
      pagebreak: { 
        mode: ['css', 'legacy'], 
        avoid: [
          '.content-txt',
        ],
        before: '.page-break-before',
        after: '.page-break-after'
      },
    };
    // 显示加载状态
    loadingBtn.value = true;

    // 添加短暂延迟确保DOM完全稳定
    await new Promise(resolve => setTimeout(resolve, 500));

    // 生成并下载PDF
    await html2pdf().from(element).set(opt).save();
  } catch (error) {
    ElMessage.error($t('paper.exportPdfFailed'));
  } finally {
    loadingBtn.value = false;
  }
}
// 设置密封线
watch(examDetail, async () => {
  await nextTick(); // 等待DOM更新
  if (examDialogRef.value) {
    pageNumber.value = Math.ceil(examDialogRef?.value.offsetHeight / 1040);
  }
});
watch(examDialogRef, () => {
  console.log('图片渲染DOM更新')
})
const getTotalQuestions = computed(() => {
  return questionList.value?.length ?? 0
})
const getTotalScore = computed(() => {
  if (!questionList.value || !Array.isArray(questionList.value)) return 0
  return questionList.value.reduce((sum, q: any) => sum + (+q.score || 0), 0)
})

</script>
<template>
  <el-dialog v-model="modelValue.dialogVisible" align-center :title="$t('common.previewTxt', [$t('paper.paperTxt')])"
    width="auto" :destroy-on-close="true" :close-on-click-modal="false" :before-close="handleClose">
    <div class="exam-dialog">
      <div class="flex items-center mb-[10px]">
        <span class="mr-[10px]">{{ $t('paper.paperSize') }}</span>
        <el-radio-group v-model="paperType">
          <el-radio value="a4" size="default">{{ $t('paper.a4Size') }}</el-radio>
          <el-radio value="a3" size="default">{{ $t('paper.a3Size') }}</el-radio>
        </el-radio-group>
      </div>
      <div class="border border-color:#DCDFE6 p-[24px] rounded-2xl">
        <div ref="examDialogRef" id="examBody" class="exam-body" style="width: 100%;" :style="examBodyStyle">
          <div style="font-size: 16px; color: #191919; margin-bottom: 16px;">{{ $t('paper.confidential') }}</div>
          <h2 style="margin-bottom: 11px; text-align: center;font-size: 24px;">{{ titleName }}</h2>
          <h2 style="margin-bottom: 67px;text-align: center;font-weight: bold;font-size: 36px;">{{ $t('paper.examTitle') }}</h2>
          <div style="width: 100%; display: flex; margin-bottom: 48px;">
            <div style="width: 60%;">
              <div style="font-size: 18px; line-height: 22px; margin-bottom: 12px;">{{ $t('paper.examNotice') }}</div>
              <div style="font-size: 14px; line-height: 24px; text-content">
                <p>{{ $t('paper.examNotice1', [getTotalQuestions, getTotalScore]) }}</p>
                <p>{{ $t('paper.examNotice2') }}</p>
                <p>{{ $t('paper.examNotice3') }}</p> 
              </div>
            </div>
            <div style="width: 40%;">
              <div style="font-size: 18px; line-height: 22px; margin-bottom: 16px;">{{ $t('paper.fillInfo') }}</div>
              <table>
                <tr>
                  <td width="80px">{{ $t('paper.idCard') }}</td>
                  <td v-for="item in 18" :key="item"></td>
                </tr>
                <tr>
                  <td width="80px">{{ $t('paper.studentName') }}</td>
                </tr>
              </table>
            </div>
          </div>
          <div style="width: 100%; height: 65px; margin-bottom: 48px;">
            <table>
              <tr>
                <td style="width: calc(100%/7);">{{ $t('paper.questionType') }}</td>
                <td style="width: calc(100%/7);">{{ $t('paper.section1') }}</td>
                <td style="width: calc(100%/7);">{{ $t('paper.section2') }}</td>
                <td style="width: calc(100%/7);">{{ $t('paper.section3') }}</td>
                <td style="width: calc(100%/7);">{{ $t('paper.section4') }}</td>
                <td style="width: calc(100%/7);">{{ $t('paper.section5') }}</td>
                <td style="width: calc(100%/7);">{{ $t('paper.totalScore') }}</td>
              </tr>
              <tr>
                <td>{{ $t('paper.score') }}</td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
              </tr>
            </table>
          </div>
          <div v-loading="loading" style="width: 100%; height: auto;">
            <div v-for="(item, index) in examDetail" :key="index" :style="{ marginBottom: index < examDetail.length - 1 ? '20px' : '0px' }">
              <ExamDetail :item-data="{ questions: item, index }" />
            </div>
          </div>
        </div>
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="modelValue.dialogVisible = false">
          {{ $t('paper.close') }}
        </el-button>
        <el-button type="primary" :loading="loadingBtn" @click="printExam">
          {{ $t('paper.download') }}
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>
<style lang="scss" scoped>
.exam-dialog {
  width: 100%;
  height: auto;
  max-height: 600px;
  overflow: scroll;
}

.exam-body {
  width: 210mm;
  min-height: 297mm;
  height: auto;
  min-height: 1040px;
}

.l-seal-area {
  width: 80px;
  height: auto;
}

.grap-line {
  position: relative;
}

.info {
  position: absolute;
  top: 50%;
  left: -220%;
  width: 400px;
  white-space: nowrap;
  transform: rotate(270deg);
}

.page-l {
  width: 100%;
  height: 1040px;
  border-right: 2px dotted rgb(39 39 41 / 67%);
}

.line-sign-m {
  position: absolute;
  top: 20%;
  left: 92%;
  background-color: #fff;
}

.line-sign-f {
  position: absolute;
  top: 40%;
  left: 92%;
  background-color: #fff;
}

.line-sign-x {
  position: absolute;
  top: 80%;
  left: 92%;
  background-color: #fff;
}

.image-war {
  page-break-inside: avoid;
  /* 旧浏览器兼容 */
  break-inside: avoid;
  /* 现代浏览器标准 */
  display: block;
  overflow: hidden;
}

table {
  width: 100%;
  border-collapse: collapse;
}

table,
td {
  height: 32px;
  font-size: 14px;
  text-align: center;
  vertical-align: middle;
  padding: 0px;
  border: 1px solid rgb(144, 147, 153);
}

/* PDF导出优化样式 */
@media print {
  * {
    -webkit-print-color-adjust: exact !important;
    color-adjust: exact !important;
  }
  
  .exam-body {
    font-family: 'SimSun', 'Microsoft YaHei', sans-serif !important;
    line-height: 1.6 !important;
    word-spacing: normal !important;
    letter-spacing: normal !important;
    font-size: 14px !important;
    padding: 15px !important;
    margin: 0 !important;
  }
  
  p, div, span {
    orphans: 3 !important;
    widows: 3 !important;
    page-break-inside: avoid !important;
    word-spacing: normal !important;
    letter-spacing: normal !important;
    line-height: 1.6 !important;
  }
  
  /* 防止文字被分割 */
  .text-content {
    white-space: pre-wrap !important;
    word-break: keep-all !important;
    overflow-wrap: break-word !important;
    word-spacing: normal !important;
    letter-spacing: normal !important;
  }
  
  /* 确保表格内容不被分割 */
  table {
    page-break-inside: avoid !important;
  }
  
  tr {
    page-break-inside: avoid !important;
  }
  
  td {
    page-break-inside: avoid !important;
    word-spacing: normal !important;
    letter-spacing: normal !important;
  }
  
  /* 特别处理包含括号的文本 */
  *:contains('('), *:contains(')'), *:contains('（'), *:contains('）') {
    word-spacing: 0.1em !important;
    letter-spacing: 0.05em !important;
  }
  
  /* 强制所有文本元素使用正常间距 */
  .exam-type-title,
  .q-title,
  .q-option-content {
    word-spacing: normal !important;
    letter-spacing: normal !important;
    line-height: 1.6 !important;
  }
  
  /* 确保题目类型间距正确 */
  [style*="margin-bottom"] {
    margin-bottom: 20px !important;
    page-break-inside: avoid !important;
    break-inside: avoid !important;
  }
  
  /* 最后一个题目类型不需要底部间距 */
  [style*="margin-bottom"]:last-child {
    margin-bottom: 0 !important;
  }
  
  /* 确保内联样式在PDF中正确应用 */
  *[style] {
    -webkit-print-color-adjust: exact !important;
    color-adjust: exact !important;
  }
}
</style>
